import simplejson
import time, random, sys
from hashlib import md5

from twisted.python import log
log.startLogging(sys.stdout)
from twisted.internet import reactor
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import NetstringReceiver

from collections import namedtuple
from functools import partial

RPCMessage = namedtuple("RPCMessage", "method params id")


def makeId():
    return int("0x%s" % md5("%s%s" % (time.time(), random.randint(1,500) )).hexdigest()[:12],16)

def loadRPCMessage(jd):
    return RPCMessage(method = jd["method"], params=jd.get("params",None), id=jd.get("id",None) )

JSON2RPC = partial(simplejson.loads, object_hook = loadRPCMessage )


class SimpleClient(NetstringReceiver):
    
    
    def write(self, msg):
        print "write: ", msg
        self.sendString(msg)
    
    def sendResponse(self, _result = True, _id = None):
        message = simplejson.dumps(dict(result=_result, id = _id))
        self.write(message)
        
    def sendRequest(self, _method, _params, _id = None):
        if _id is None: _id = makeId()
        
        message = simplejson.dumps(dict(method=_method, params=_params, id=_id))        
        self.write(message)
    
    def recieve(self, msg):
        try:
            message = simplejson.loads(msg)
            if message.has_key("method"):
                self.factory.handle(JSON2RPC(msg),self)
            else:
                print "Recieved response: ", msg
        except Exception, e:
            print "Syntax error: ", e , msg            
            
    def stringReceived(self, msg):
        print "Recieved: ", msg
        self.recieve(msg)
        


class AuthHandlerTest(ClientFactory):
    protocol = SimpleClient
    
    def handle(self, message, p):
        
        try:
            if message.method == "loader":
                self.loader(message, p)
        except Exception, e:
            print "Bad Message", e ,  message
            
    
    def handle_requests(self, message, p):
        if message.method == "loader":
            self.loader(message, p)        
            
        
                
    def loader(self, message, p):
        
        if message.params == "auth":
            print "Was asked to load authorization package from server"
            p.sendResponse(True, message.id)
            p.sendRequest("auth.login",{"user":"admin","password":"test"}, makeId())
            p.sendRequest("auth.test",None, makeId());
        else:
            raise Exception("Unexpected params: %s " % message.params )
    
        
        



reactor.connectTCP("127.0.0.1", 4747, AuthHandlerTest())
reactor.run()
